import { FarrisDesignBaseComponent } from '@farris/designer-element';
import { DesignerEnvType, FormBasicService } from '@farris/designer-services';
import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { cloneDeep } from 'lodash-es';
import { default as FdToolBarComponent, default as ToolBarComponent } from '../../fd-toolbar';
import { ToolBarItemProp } from '../property/property-config';
import { ToolBarItemSchema, ToolBarItemType } from '../schema/schema';


export interface ToolBarItemOptions {
    isChildOfToolBar?: boolean;
    isChildOfButton?: boolean;
    viewModelId: string;
    componentId: string;
}
export default class FdToolBarItemComponent extends FarrisDesignBaseComponent {

    envType: DesignerEnvType;

    component: ToolBarItemType;

    /** toolBar组件的子级，一级按钮 */
    public isChildOfToolBar: boolean;

    /** 按钮的子级，二级按钮 */
    public isChildOfButton: boolean;

    /** 按钮的根组件，即toolbar组件 */
    root: ToolBarComponent;

    items: ToolBarItemType[];
    extendOptions: ToolBarItemOptions;
    toolBarItemList: FdToolBarItemComponent[];

    button: HTMLElement;

    /** 当前toolbar中选中的按钮 */
    get selectedId() {
        if (this.isChildOfToolBar) {
            return this.parent.selectedId;
        } else {
            return this.root.selectedId;
        }

    }

    constructor(component: any, options: any, extendOptions?: ToolBarItemOptions) {
        super(component, options);

        const serviceHost = this.options.designerHost;
        const formBasicService = serviceHost.getService('FormBasicService') as FormBasicService;
        if (formBasicService) {
            this.envType = formBasicService.envType;
        }

        if (this.envType === DesignerEnvType.noCode) {
            // 零代码场景下不选中按钮
            this.checkable = false;
        }

        this.applyClassToComponent = false;
        this.items = component.items;
        if (extendOptions) {
            this.extendOptions = this.extendOptions;
            const { isChildOfButton, isChildOfToolBar } = extendOptions;
            this.isChildOfButton = isChildOfButton;
            this.isChildOfToolBar = isChildOfToolBar;
            this.viewModelId = extendOptions.viewModelId;
            this.componentId = extendOptions.componentId;
        }
        this.root = this.getParent();
    }

    getDefaultSchema(): any {
        // 这里cloneDeep不能删
        return cloneDeep(ToolBarItemSchema);
    }

    init(): void {
        // 新建子级组件实例
        const options = Object.assign({}, this.options, { childComponents: [], parent: this });
        this.toolBarItemList = (this.items || []).map(item => {
            const toolBarItem = new FdToolBarItemComponent(item, options, { isChildOfButton: true, viewModelId: this.viewModelId, componentId: this.componentId });
            return toolBarItem;
        });
    }


    render(): any {
        this.init();
        return this.renderTemplate(this.type, {
            component: this.component,
            toolBarItemList: this.toolBarItemList,
            isChildOfToolBar: this.isChildOfToolBar,
            isChildOfButton: !this.isChildofToolBar(),
            popDirection: this.root.popDirection,
            showMenuInToolbarItem: this.envType == DesignerEnvType.designer
        });
    }


    attach(element: HTMLElement): Promise<any> {
        this.element = element;
        this.button = this.element.querySelector('button');
        const superAttach = super.attach(this.element);

        // 删除
        const removeButton = element.querySelector('[ref="removeButton"]');
        this.attachRemoveEvent(removeButton);

        // 复制
        const cloneButton = element.querySelector('[ref="copyButton"]');
        this.attachCopyEvent(cloneButton);

        // 新增子级
        const appendChildButton = element.querySelector('[ref="appendChildButton"]');
        this.attachAppendChildEvent(appendChildButton);


        if (this.options.parent instanceof FdToolBarItemComponent) {
            // 二级按钮新增同级
            const appendSameButton = element.querySelector('[ref="appendSame"]');
            this.attachAppendSame(appendSameButton);

            // 二级按钮上移
            const appendMoveUpButton = element.querySelector('[ref="moveUp"]');
            this.appendMoveUpAndDown(appendMoveUpButton, 'moveUp');

            // 二级按钮下移
            const appendMoveDownButton = element.querySelector('[ref="moveDown"]');
            this.appendMoveUpAndDown(appendMoveDownButton, 'moveDown');
        }

        // 模拟点击当前选中的按钮
        if (this.parent.selectedId && this.parent.selectedId === this.id) {
            setTimeout(() => {
                // 增加判断条件：当前页面上没有选中toolbar外的控件时，才触发按钮的点击。场景是先选中子表弹出编辑区域内的headertoolbar按钮，再选中父级tabPage，若没有这个判断，则焦点不能转移到TabPage上
                if (document.getElementsByClassName('dgComponentSelected').length === 0) {
                    this.element.click();
                }
            });
        }

        // 展开工具栏下拉按钮列表
        const showListButton = element.querySelector('[ref="dropdown-button"]');
        const list = element.querySelector('[ref="dropdown-button"]+div');
        this.addEventListener(showListButton, 'click', (event) => {
            event.stopPropagation();
            if (list.classList.contains('d-block')) {
                list.classList.remove('d-block');
                list.classList.add('d-none');

            } else if (list.classList.contains('d-none')) {
                // 关闭其他一级按钮的下拉列表
                const otherLists = this.parent.element.querySelectorAll('[ref="dropdown-button"]+div');
                if (otherLists && otherLists.length) {
                    otherLists.forEach(otherList => {
                        otherList.classList.remove('d-block');
                        otherList.classList.add('d-none');
                    });

                }

                list.classList.remove('d-none');
                list.classList.add('d-block');

            }
        });

        // 绑定子级事件
        this.root.attach.call(this, this.element);

        // 新增同级
        return superAttach;
    }
    /**
     * 按钮被取消选中后，需要将toolbar上记录的selectedId置空，否则会触发按钮的点击事件
     */
    afterComponentCancelClicked() {
        this.closeAllDropdownPanel();
        this.setSelectedId(null);
    }

    /**
     * 选中按钮后事件，由基类调用
     * @param event 选中event
     */
    afterComponentClicked(event?: PointerEvent) {
        this.parent.toolBarItemList.forEach(i => {
            const cmpGroup = i.element.querySelector('.component-btn-group');
            if (cmpGroup && cmpGroup.classList) {
                cmpGroup.classList.remove('d-flex');
                cmpGroup.classList.remove('d-none');
            }
        });

        // 若点击二级按钮，需要展开一级按钮旁边的下拉框
        if (this.isChildOfButton) {
            // this.closeAllDropdownPanel();

            // 打开所属一级按钮的下拉面板
            const list = this.parent.element.querySelector('[ref="dropdown-button"]+div') as HTMLElement;
            list.classList.remove('d-none');
            list.classList.add('d-block');
        }
        // 点击一级按钮，关闭下拉框面板
        if (this.isChildOfToolBar) {
            this.closeAllDropdownPanel();
        }

        // 手动触发点击组件事件  展示属性面板
        this.triggerComponentClicked(event);

        // 设置操作按钮的位置
        this.setPositionOfToolbarIcon(this.button);

        // 在整个toolbar上记录当前选中按钮的id
        if (this.parent.selectedId !== this.id) {
            this.parent.setSelectedId(this.id);
        }

        // 二级按钮增加鼠标移入移出事件
        this.addToolBarItemButtonMouseEvent(this.element);
    }

    /**
     * 关闭二级按钮下拉框面板
     */
    private closeAllDropdownPanel() {
        // 关闭其他一级按钮的下拉列表
        const otherLists = this.root.element.querySelectorAll('[ref="dropdown-button"]+div');
        if (otherLists && otherLists.length) {
            otherLists.forEach(otherList => {
                otherList.classList.remove('d-block');
                otherList.classList.add('d-none');
            });

        }
    }
    /**
     * 二级按钮增加鼠标移入移出事件。因为二级按钮是上下排列，按钮的工具栏会遮挡上方的按钮，所以限定在鼠标移入时才显示工具栏
     * @param button
     */
    private addToolBarItemButtonMouseEvent(button) {
        if (!(this.parent instanceof FdToolBarComponent)) {
            this.addEventListener(button, 'mouseenter', (event) => {
                if (button.classList.contains('dgComponentSelected')) {
                    const buttomGroup = button.querySelector('.component-btn-group');
                    buttomGroup.classList.remove('d-none');

                    // 为适应拖拽、界面收折等场景，每次都重新计算图标位置
                    this.setPositionOfToolbarIcon(this.button);
                }
            });
            this.addEventListener(button, 'mouseleave', (event) => {
                if (button.classList.contains('dgComponentSelected')) {
                    const buttomGroup = button.querySelector('.component-btn-group');
                    if (!buttomGroup.classList.contains('d-none')) {
                        buttomGroup.classList.add('d-none');
                    }
                }
            });
        }
    }

    private attachRemoveEvent(element: Element) {
        this.addEventListener(element, 'click', (event) => {
            event.stopPropagation();
            this.remove();
        });
    }

    private attachCopyEvent(element: Element) {
        this.addEventListener(element, 'click', (event) => {
            event.stopPropagation();
            this.copy();
        });
    }

    private attachAppendChildEvent(element: Element) {
        this.addEventListener(element, 'click', (event) => {
            event.stopPropagation();
            this.appendChild();
        });
    }

    private attachAppendSame(element: Element) {
        this.addEventListener(element, 'click', (event) => {
            event.stopPropagation();
            this.options.parent.appendItem();
        });
    }
    private appendMoveUpAndDown(element: Element, action: string) {
        if (this.appendMoveUpAndDown) {
            this.addEventListener(element, 'click', (event) => {
                event.stopPropagation();
                this.options.parent.moveUpAndDown(this.component.id, action);
            });
        }

    }
    /**
     * 二级按钮上移下移
     * @param targetBtnId 当前移动的按钮id
     * @param action 上移/下移
     */
    moveUpAndDown(targetBtnId: string, action: string) {
        const index = this.items.findIndex(i => i.id === targetBtnId);
        if (index < 0) {
            return;
        }
        const targetBtn = this.items[index];
        if (action === 'moveUp' && index > 0) {
            this.items.splice(index, 1);
            this.items.splice(index - 1, 0, targetBtn);

            this.root.rebuild();
        }

        if (action === 'moveDown' && index < this.items.length - 1) {
            this.items.splice(index, 1);
            this.items.splice(index + 1, 0, targetBtn);

            this.root.rebuild();
        }
    }
    /**
     * 设置操作按钮的位置
     * @param button  当前选中的按钮DOM节点
     */
    setPositionOfToolbarIcon(selectedButton: HTMLElement) {
        const toolbarEle = selectedButton.previousElementSibling as HTMLElement;
        if (toolbarEle) {
            const toolbarEleRect = toolbarEle.getBoundingClientRect();

            const toolbarDivPanelEle = toolbarEle.children[0] as HTMLElement;
            const toolbarDivPanelEleRect = toolbarDivPanelEle.getBoundingClientRect();

            toolbarDivPanelEle.style.top = toolbarEleRect.top + 'px';
            toolbarDivPanelEle.style.left = (toolbarEleRect.left - toolbarDivPanelEleRect.width) + 'px';
        }

    }

    private appendChild() {
        this.appendItem();
    }

    appendItem() {
        const newItemMetadata = cloneDeep(ToolBarItemSchema);
        this.root.appendItem.call(this, newItemMetadata);
    }

    private remove() {
        // 移除父组件中的按钮实例
        const parent = this.options.parent;
        parent.removeToolBarItem(this.component.id);
    }

    removeToolBarItem(id: string) {
        this.root.removeToolBarItem.call(this, id);
    }

    confirmRemoveToolbarItem(id: string) {
        this.root.confirmRemoveToolbarItem.call(this, id);
    }

    cloneToolBarItem(id: string) {
        this.root.cloneToolBarItem.call(this, id);
    }

    private copy() {
        const parent = this.options.parent;
        parent.cloneToolBarItem(this.component.id);
    }

    triggerComponentClicked(e: PointerEvent) {
        // 使用父组件的componentClicked事件  传递不同的参数
        const parent = this.getParent();
        parent.selectedToolbarItem = this;
        parent.emit('componentClicked', { componentInstance: this, e });
    }

    getParent() {
        let parent = this.options.parent;

        while (!(parent instanceof ToolBarComponent)) {
            parent = parent.options.parent;
        }
        return parent;
    }

    isChildofToolBar() {
        const parent = this.options.parent;
        return parent instanceof ToolBarComponent;
    }

    /**
     * 组装属性面板配置数据
     */
    getPropertyConfig(): ElementPropertyConfig[] {
        const serviceHost = this.options && this.options.designerHost;
        const prop: ToolBarItemProp = new ToolBarItemProp(serviceHost.getService('Injector'), this.viewModelId);
        const propertyConfig: ElementPropertyConfig[] = prop.getPropertyConfig(this.component, false, !this.isChildOfButton);
        return propertyConfig;
    }

    /**
     * 属性变更后事件：默认监听样式类属性变更，并触发模板重绘
     * @param changeObject 变更集
     * @param propertyIDs 需要额外监听的属性ID列表
     */
    onPropertyChanged(changeObject: any): void {
        this.root.onPropertyChanged(changeObject);
    }

    positionTool() {
        const container = document.createElement('div');
        container.classList.add('position.absolute', 'component-btn-group');
        document.body.appendChild(container);
    }

    setSelectedId(id: string) {
        // this.selectedId = id;
        this.parent.setSelectedId(id);
    }

    registerDnd() {
        this.root.registerDnd.call(this);
    }

    dragEnd() {
        this.root.dragEnd.call(this);
    }

    /**
    * 涉及到按钮绑定事件的删除，故触发同步actions操作
    */
    syncActions() {
        const webCmdService = this.options.designerHost.getService('WebCmdService');
        webCmdService.syncActions();
    }

}
